/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.yami.shop.bean.enums.FlowVisitEnum;
import com.yami.shop.bean.model.FlowLog;
import com.yami.shop.bean.vo.statistics.HotStatisticsVO;
import com.yami.shop.bean.vo.statistics.PlatformStatisticsVO;
import com.yami.shop.bean.vo.statistics.TrendStatisticsVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.util.Arith;
import com.yami.shop.dao.StatisticsMapper;
import com.yami.shop.service.FlowLogService;
import com.yami.shop.service.StatisticsService;
import lombok.AllArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chiley
 * @create 2022/5/16 15:34
 */
@Service
@AllArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {

    private final StatisticsMapper statisticsMapper;
    private final FlowLogService flowLogService;


    @Override
    public PlatformStatisticsVO getPlatformStatistics() {
        // 今日
        Date today = DateUtil.beginOfDay(new Date());
        final DateTime startDate = DateUtil.offsetDay(today, -29);

        // 基本信息
        PlatformStatisticsVO platformStatisticsVO = getBaseStatisticsVO();
        // 今日待办、实时概况
        loadCurrentHandle(platformStatisticsVO, today);
        // 数据趋势
        loadDataTrend(platformStatisticsVO, startDate, today);
        // 热卖信息
        loadHotData(platformStatisticsVO, today);

        // 实时数据处理
        long visitNum = setTodayVisitors(platformStatisticsVO);

        // 流量趋势-今日的数据
        TrendStatisticsVO trendStatisticsVO = platformStatisticsVO.getTrendStatisticsList().get(platformStatisticsVO.getTrendStatisticsList().size() - 1);
        trendStatisticsVO.setVisitNum(visitNum);
        trendStatisticsVO.setUserNum(platformStatisticsVO.getTodayVisitors());
        return platformStatisticsVO;
    }

    @Override
    public PlatformStatisticsVO platformRealTimeOverview(Date startTime) {
        startTime = DateUtil.beginOfDay(startTime);
        PlatformStatisticsVO platformStatisticsVO = new PlatformStatisticsVO();
        // 今日待办、实时概况
        loadCurrentHandle(platformStatisticsVO, startTime);
        return platformStatisticsVO;
    }

    /**
     * 从缓存中获取今天的访客人数并返回访客数
     *
     * @return
     */
    private long setTodayVisitors(PlatformStatisticsVO platformStatisticsVO) {
        // 实时数据处理
        Set<String> visitorSet = new HashSet<>();
        long visitNum = 0;
        for (FlowLog flowLog : flowLogService.getFlowLogListByCache()) {
            if (!FlowVisitEnum.isVisitOrShare(flowLog.getVisitType())) {
                continue;
            }
            visitorSet.add(flowLog.getUuid());
            visitNum++;
        }
        platformStatisticsVO.setTodayVisitors((long) visitorSet.size());
        return visitNum;
    }

    @Override
    public List<TrendStatisticsVO> loadDataTrend(PlatformStatisticsVO platformStatisticsVO, Date startDate, Date endDate) {

        List<TrendStatisticsVO> flowTrendList = statisticsMapper.flowTrend(startDate, endDate);
        List<TrendStatisticsVO> transactionTrendList = statisticsMapper.transactionTrend(startDate, endDate);

        List<TrendStatisticsVO> trendStatisticsVOList = new ArrayList<>();
        Map<String, TrendStatisticsVO> flowTrendMap = CollUtil.isNotEmpty(flowTrendList) ? flowTrendList.stream().collect(Collectors.toMap(TrendStatisticsVO::getDate, t -> t)) : new HashMap<>(0);
        Map<String, TrendStatisticsVO> transactionTrendMap = CollUtil.isNotEmpty(transactionTrendList) ? transactionTrendList.stream().collect(Collectors.toMap(TrendStatisticsVO::getDate, t -> t)) : new HashMap<>(0);
        // 数据时间跨度所包含的天数
        final long days = DateUtil.betweenDay(startDate, endDate, true);
        for (int i = 0; i <= days; i++) {
            String formatTime = DateUtil.format(startDate, "yyyy-MM-dd");
            TrendStatisticsVO trendStatisticsVO = new TrendStatisticsVO();
            trendStatisticsVO.setDate(formatTime);
            if (flowTrendMap.containsKey(formatTime)) {
                TrendStatisticsVO flowTrend = flowTrendMap.get(formatTime);
                trendStatisticsVO.setUserNum(flowTrend.getUserNum());
                trendStatisticsVO.setVisitNum(flowTrend.getVisitNum());
            } else {
                trendStatisticsVO.setUserNum(Constant.ZERO_LONG);
                trendStatisticsVO.setVisitNum(Constant.ZERO_LONG);
            }
            if (transactionTrendMap.containsKey(formatTime)) {
                TrendStatisticsVO transactionTrend = transactionTrendMap.get(formatTime);
                trendStatisticsVO.setAmount(transactionTrend.getAmount());
            } else {
                trendStatisticsVO.setAmount(Constant.ZERO_DOUBLE);
            }
            trendStatisticsVOList.add(trendStatisticsVO);
            startDate = DateUtil.offsetDay(startDate, 1);
        }
        if (platformStatisticsVO != null) {
            platformStatisticsVO.setTrendStatisticsList(trendStatisticsVOList);
        }
        return trendStatisticsVOList;
    }


    private void loadHotData(PlatformStatisticsVO platformStatisticsVO, Date today) {
        List<HotStatisticsVO> hotProdList = loadHotProdByDate(today, new Date());
        platformStatisticsVO.setHotProdList(hotProdList);

        List<HotStatisticsVO> hotShopList = loadHotShopByDate(today, new Date());
        for (HotStatisticsVO hotStatisticsVO : hotShopList) {
            if (Objects.equals(hotStatisticsVO.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                hotStatisticsVO.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
            hotStatisticsVO.setShopId(null);
        }
        platformStatisticsVO.setHotShopList(hotShopList);
    }


    @Override
    public List<HotStatisticsVO> loadHotProdByDate(Date start, Date end) {
        return statisticsMapper.getHotProdListByDate(start, end, I18nMessage.getLang());

    }


    @Override
    public List<HotStatisticsVO> loadHotShopByDate(Date start, Date end) {
        return statisticsMapper.getHotShopListByDate(start, end, I18nMessage.getLang());
    }

    private void loadCurrentHandle(PlatformStatisticsVO platformStatisticsVO, Date today) {
        // 昨天
        Date yesterday = DateUtil.beginOfDay(DateUtil.offsetDay(today, -1));
        // 前七天
        Date sevenDay = DateUtil.beginOfDay(DateUtil.offsetDay(today, -7));
        // 前30天
        Date thirtyDay = DateUtil.beginOfDay(DateUtil.offsetDay(today, -30));
        PlatformStatisticsVO platformStatisticsNew = statisticsMapper.getAuditAndPlatformStatistics(today, yesterday, sevenDay, thirtyDay);

        platformStatisticsVO.setProdAuditNum(platformStatisticsNew.getProdAuditNum());
        platformStatisticsVO.setShopAuditNum(platformStatisticsNew.getShopAuditNum());
        platformStatisticsVO.setDistributionAuditNum(platformStatisticsNew.getDistributionAuditNum());
        platformStatisticsVO.setWithdrawalAuditNum(platformStatisticsNew.getWithdrawalAuditNum());
        platformStatisticsVO.setCurrentOrderNum(platformStatisticsNew.getCurrentOrderNum());
        platformStatisticsVO.setCurrentUserNum(platformStatisticsNew.getCurrentUserNum());
        platformStatisticsVO.setCurrentShopNum(platformStatisticsNew.getCurrentShopNum());
        platformStatisticsVO.setCurrentPayAmount(platformStatisticsNew.getCurrentPayAmount());
        platformStatisticsVO.setCurrentProdNum(platformStatisticsNew.getCurrentProdNum());
        platformStatisticsVO.setCurrentProdCommNum(platformStatisticsNew.getCurrentProdCommNum());
        if (DateUtil.isSameDay(today, new Date())) {
            setTodayVisitors(platformStatisticsVO);
        } else {
            platformStatisticsVO.setTodayVisitors(platformStatisticsNew.getTodayVisitors());
        }
        platformStatisticsVO.setYesterdayVisitors(platformStatisticsNew.getYesterdayVisitors());
        platformStatisticsVO.setFirstSevenDayVisitors(platformStatisticsNew.getFirstSevenDayVisitors());
        platformStatisticsVO.setFirstThirtyDayVisitors(platformStatisticsNew.getFirstThirtyDayVisitors());
    }

    /**
     * 获取基本信息
     *
     * @return
     */
    private PlatformStatisticsVO getBaseStatisticsVO() {
        // 本月的开始时间
        DateTime monthStartTime = DateUtil.beginOfMonth(new Date());
        // 上一个月的开始时间
        DateTime lastMonthStartTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(monthStartTime, -1));
        List<PlatformStatisticsVO> baseInfoStatisticsList = statisticsMapper.getPlatformBaseInfo(lastMonthStartTime, monthStartTime);
        PlatformStatisticsVO platformStatisticsVO = null;
        PlatformStatisticsVO oldPlatformStatisticsVO = null;
        for (PlatformStatisticsVO infoStatisticsVO : baseInfoStatisticsList) {
            // 总的数据
            if (Objects.isNull(platformStatisticsVO)) {
                platformStatisticsVO = infoStatisticsVO;
                continue;
            }
            // 上一月的数据
            if (Objects.isNull(oldPlatformStatisticsVO)) {
                oldPlatformStatisticsVO = infoStatisticsVO;
                continue;
            }
            // 当月数据，并处理增长率
            if (Objects.isNull(platformStatisticsVO.getProdNumRatio())) {
                platformStatisticsVO.setProdNumRatio(loadRatio(infoStatisticsVO.getProdNum(), oldPlatformStatisticsVO.getProdNum()));
                platformStatisticsVO.setUserNumRatio(loadRatio(infoStatisticsVO.getUserNum(), oldPlatformStatisticsVO.getUserNum()));
                platformStatisticsVO.setOrderNumRatio(loadRatio(infoStatisticsVO.getOrderNum(), oldPlatformStatisticsVO.getOrderNum()));
                platformStatisticsVO.setShopNumRatio(loadRatio(infoStatisticsVO.getShopNum(), oldPlatformStatisticsVO.getShopNum()));
                platformStatisticsVO.setRefundNumRatio(loadRatio(infoStatisticsVO.getRefundNum(), oldPlatformStatisticsVO.getRefundNum()));
            }
        }
        return platformStatisticsVO;
    }

    private Double loadRatio(Long value, Long oldValue) {
        if (Objects.isNull(value) || Objects.isNull(oldValue)) {
            return Constant.ZERO_DOUBLE;
        }
        if (Objects.equals(value, oldValue)) {
            return Constant.ZERO_DOUBLE;
        }
        // 能执行以下步骤代表新旧数据是不相等的
        if (Objects.equals(value, Constant.ZERO_LONG) || Objects.equals(oldValue, Constant.ZERO_LONG)) {
            // 新数据为0， 旧数据不为0，则下降100%
            if (Objects.equals(value, Constant.ZERO_LONG)) {
                return -100D;
            }
            // 新数据不为0， 旧数据为0，则增长100%
            if (Objects.equals(oldValue, Constant.ZERO_LONG)) {
                return 100D;
            }
        }
        // ((当月数据-上一月数据)/上一月数据) * 100
        return Arith.mul(Arith.div(Arith.sub(value, oldValue), oldValue, 4), 100);
    }
}
